#!/bin/sh
#
#  Copyright (c) 2014 - 2018 by NuTyX team (http://nutyx.org)
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
#  USA.
#
#
# This code is base on the documented init.in script file from BLFS
# http://www.linuxfromscratch.org/blfs/view/svn/postlfs/initramfs.html
#

# Default Quota in percent for rootfs
ROOTFS_QUOTA=50

PATH="/bin:/usr/bin:/sbin:/usr/sbin:/lib:/lib/systemd"
export PATH

problem()
{
   printf "Encountered a problem!\n\nDropping you to a shell.\n\n"
   sh
}

no_device()
{
   printf "The device %s, which is supposed to contain the\n" $1
   printf "root file system, does not exist.\n"
   printf "Please fix this problem and exit this shell.\n\n"
}

no_mount()
{
   printf "Could not mount device %s\n" $1
   printf "Sleeping forever. Please reboot and fix the kernel command line.\n\n"
   printf "Maybe the device is formatted with an unsupported file system?\n\n"
   printf "Or maybe filesystem type autodetection went wrong, in which case\n"
   printf "you should add the rootfstype=... parameter to the kernel command line.\n\n"
   printf "Available partitions:\n"
}

do_mount_root()
{
   [ -n "$rootflags" ] && rootflags="$rootflags,"
   rootflags="$rootflags$ro"

   case "$root" in
      /dev/* ) device=$root ;;
      UUID=* ) eval $root; device="/dev/disk/by-uuid/$UUID"  ;;
      LABEL=*) eval $root; device="/dev/disk/by-label/$LABEL" ;;
      ""     ) echo "No root device specified." ; problem    ;;
   esac

if [ ! -z "$croot" ]; then
   cryptsetup luksOpen --key-file=/root/.crypto/keyfile.bin $croot CROOT
   device=/dev/mapper/CROOT
fi

   while [ ! -b "$device" ] ; do
       no_device $device
       problem
   done
   if  [ "$rootfstype" != "auto" ]; then
	rootfstype=`print_file_system $device`
   fi
   if [ "$rootfstype" == "no" ]; then
       no_mount $device
       cat /proc/partitions
       while true ; do sleep 10000 ; done
   fi
   [ -z "$overlayroot" ] && mountpoint=/.root  || mountpoint=/.roRoot
   mkdir -p $mountpoint
   [ "$verbose" == "no" ] || printf "mount -n -t $rootfstype -o $rootflags $device $mountpoint ...\n"
   mount -n -t $rootfstype -o $rootflags $device $mountpoint
   if [ $? -gt 0 ]; then
       no_mount $device
       cat /proc/partitions
       while true ; do sleep 10000 ; done
   else
       log_info_msg "Mounting root file system ${root} in read-only mode..."
       evaluate_retval
   fi
   if [ -n "$overlayroot" ]; then
     overlaydevice=$overlayroot;         # /dev/mapper/<vg>/<lv>
     mkdir -p /mnt/OVL
     if ! mount -n "$overlaydevice" /mnt/OVL; then
       no_mount $overlaydevice
       cat /proc/partitions
       while true ; do sleep 10000 ; done
     else
       log_info_msg "Mounting overlay upper file system ${overlayroot}..."
       evaluate_retval
     fi
     mkdir -p /mnt/OVL/upper
     mkdir -p /mnt/OVL/work
     mount -n -t overlay -o lowerdir=$mountpoint,upperdir=/mnt/OVL/upper,workdir=/mnt/OVL/work overlayrootfs /.root 
     if [ $? -gt 0 ]; then
       no_mount "overlayrootfs"
       cat /proc/partitions
       while true ; do sleep 10000 ; done
     else
       log_info_msg "Mounting overlay root filesystem..."
       evaluate_retval
     fi
   fi
}

do_mount_in_ram()
{
	# squasfs files are in /media/cdrom/boot on the initrd
	SQFS="/media/cdrom/boot"
	mkdir -p /boot
	# RW folders: This are tiny size and part of them already exist so
	# Lets copy them, won't restrict to much the memory
	for DIR in var run etc sbin bin home
	do
		if [ -f $SQFS/$DIR.squashfs ];then
			mkdir /DIR
			[ "$verbose" == "no" ] || echo "mount -o loop -t squashfs $SQFS/$DIR.squashfs /DIR"
			mount -o loop -t squashfs $SQFS/$DIR.squashfs /DIR || problem
			mkdir -p /$DIR
			cp -a /DIR/* /$DIR/ > /dev/null 2>&1
			umount /DIR
			rm -r /DIR
			# In case we have enough RAM /media/cdrom/ will be unmounted
			[ "$verbose" == "no" ] || echo "cp $SQFS/$DIR.squashfs /boot/$DIR.squashfs"
			cp $SQFS/$DIR.squashfs /boot/
		fi
	done

	# root is not copied but created "from scratch"
	#
	mkdir -p /root
	chmod 750 /root
	cp /etc/skel/.bash* /root
	if [ -f $SQFS/root.squashfs ]; then
		[ "$verbose" == "no" ] || echo "cp $SQFS/root.squashfs /boot/root.squashfs"
		cp $SQFS/root.squashfs /boot/
	fi
	# lib64
	if [ -f $SQFS/lib64.squashfs ];then
		[ "$verbose" == "no" ] || echo "cp $SQFS/lib64.squashfs /boot/lib64.squashfs"
		cp $SQFS/lib64.squashfs /boot/
	fi
	# RO folders: Only bigger directories are going to be mounted and overlayed
	OVL=/boot/ovl
	ROOTFS_OK="yes"
	for DIR in mnt usr lib opt
	do
		if [ -f $SQFS/$DIR.squashfs ];then
			OVLU=$OVL/$DIR-u
			OVLW=$OVL/$DIR-w
			mkdir -p /$DIR
			mkdir -p $OVLU
			mkdir -p $OVLW

			# How much RAM for rootfs:
			MEM_TOTAL=`cat /proc/meminfo|grep MemTotal|sed "s/[^[:digit:]]*//g"`
			MEM_AVAIL=`cat /proc/meminfo|grep MemAvail|sed "s/[^[:digit:]]*//g"`
			MEM_USED=$((MEM_TOTAL - MEM_AVAIL))
			ROOTFS_TOTAL=$((MEM_TOTAL * ROOTFS_QUOTA / 100))
			ROOTFS_AVAIL=$((ROOTFS_TOTAL - MEM_USED))
			MAX_ROOTFS_SIZE=$((ROOTFS_AVAIL * 90 / 100 ))
			SQFS_SIZE=`ls -s $SQFS/$DIR.squashfs| cut -d " " -f1`
			# We going to keep 10 % as reserve (calculation rounding issue etc)
			if [ $SQFS_SIZE -gt $((ROOTFS_AVAIL * 90 / 100 )) ];then
				# Not enough RAM
				[ "$verbose" == "no" ] || printf "mount -o loop -t squashfs %s/%s.squashfs /%s\n" $SQFS/$DIR.squashfs /$DIR
				[ "$verbose" == "no" ] || printf "not enough space in RAM\n"
				mount -o loop -t squashfs $SQFS/$DIR.squashfs /$DIR || problem
				[ "$verbose" == "no" ] || sleep 5
				ROOTFS_OK="no"
			else
				# Still enough RAM
				[ "$verbose" == "no" ] || printf "still enough RAM, cp  %s /boot\n" $SQFS/$DIR.squashfs
				cp $SQFS/$DIR.squashfs /boot/
				mount -o loop -t squashfs /boot/$DIR.squashfs /$DIR || problem
				[ "$verbose" == "no" ] || sleep 5
			fi
			# Overlay
			[ "$verbose" == "no" ] || echo "mount -n -t overlay -o lowerdir=/$DIR,upperdir=$OVLU,workdir=$OVLW /$DIR"
			mount -n -t overlay overlay -o lowerdir=/$DIR,upperdir=$OVLU,workdir=$OVLW /$DIR
			[ "$verbose" == "no" ] || sleep 5
		fi
	done
	if [ "$ROOTFS_OK" == "yes" ]; then
		cp /media/cdrom/boot/kernel* /boot/
		mkdir -p /boot/grub/fonts
		cp /media/cdrom/boot/grub/fonts/unicode.pf2 /boot/grub/fonts/unicode.pf2
		cp /media/cdrom/boot/grub/splash.png /boot/grub/splash.png
		if [ ! -d /media/cdrom/`uname -m` ]; then
			umount /media/cdrom
			eject $DEV > /dev/null 2>&1
		fi
	fi 
}
find_media() {
	local PI FSIZE MSIZE
	EXPECT_LABEL="yaolinuxcd"
	if [ -n "$fromiso" ]; then
		mkdir -p /media/fromdev
		mount -o ro ${fromdev} /media/fromdev
		modprobe loop
		LOOPDEV=`losetup -f`
		losetup $LOOPDEV /media/fromdev${fromiso}
	fi

	for SYS in /sys/block/*; do
		[ "$verbose" == "no" ] || printf "Looking in %s for media\n" $SYS
		[ ! -d "$SYS" ] && continue
		DEV=/dev/$(basename $SYS)
                [ ! -b $DEV ] && continue
		eval `/sbin/blkid $DEV|cut -d ":" -f2`
		if [ ${LABEL} == ${EXPECT_LABEL} ]  2>/dev/null ; then
                        if [ -b ${DEV}1 ]; then
                           ln -sf ${DEV}1 /dev/yaolinux-cd
                        else
                           ln -sf ${DEV} /dev/yaolinux-cd
                        fi
			mkdir  -p /media/cdrom 2>/dev/null
			[ "$verbose" == "no" ] || printf "mount -n /dev/yaolinux-cd /media/cdrom\n"
			mount -n /dev/yaolinux-cd /media/cdrom
			break
		fi
	done
}
do_resize_rootfs() {
	MEM_TOTAL=`cat /proc/meminfo|grep MemTotal|sed "s/[^[:digit:]]*//g"`
	MEM_TOTAL=$((MEM_TOTAL / 1024 / 100))
	[ $MEM_TOTAL -gt 15 ] && ROOTFS_QUOTA=60
	[ $MEM_TOTAL -gt 35 ] && ROOTFS_QUOTA=75
	[ $MEM_TOTAL -gt 75 ] && ROOTFS_QUOTA=80
	[ $MEM_TOTAL -gt 100 ] && ROOTFS_QUOTA=85
	[ $MEM_TOTAL -gt 300 ] && ROOTFS_QUOTA=90

	mount -o remount,size=${ROOTFS_QUOTA}%,noatime /
	mount -o remount,size=${ROOTFS_QUOTA}%,noatime tmpfs
	mount -o remount,size=${ROOTFS_QUOTA}%,noatime devtmpfs
}
MainLoop(){
   while [ ! -f /root/boot ];
   do
	if [ "$verbose" == "yes" ]; then
		ListModules
		printf "Launch /sbin/setup-nutyx ...\n"
	fi
	/sbin/setup-nutyx || problem
   done
   clear
}
LoadModules() {
 for i in dm-mod md-mod ehci-pci overlay \
 xhci-pci xhci-hcd ehci-hcd nls_iso8859_1 \
 uhci-hcd uas sr_mod usb-storage loop \
 squashfs isofs vfat fat nls_cp437 \
 serio libps2 atkbd i8042
 do
  if [ "$verbose" == "yes" ]; then
    modprobe -v $i
  else
    modprobe $i
  fi
 done

}
ListModules() {
  lsmod
  printf "Press <enter> to continue ...\n"
  read a
}
# **********
# Begin here
# **********
printf "Starting initrd...\n"

init=/sbin/init
overlayroot=
root=
rootdelay=
rootfstype=auto
ro="ro"
rootflags=
device=
verbose="no"
fromdev=/dev/sdb1
fromiso=

. /lib/lsb/init-functions

do_mount_virtualfs

read -r cmdline < /proc/cmdline

for param in $cmdline ; do
  case $param in
    init=*       ) init=${param#init=}               ;;
    root=*       ) root=${param#root=}               ;;
    croot=*      ) croot=${param#croot=}; root=$croot;;
    rootdelay=*  ) rootdelay=${param#rootdelay=}     ;;
    overlayroot=*) overlayroot=${param#overlayroot=} ;;
    rootfstype=* ) rootfstype=${param#rootfstype=}   ;;
    rootflags=*  ) rootflags=${param#rootflags=}     ;;
    fromdev=*    ) fromdev=${param#fromdev=}         ;;
    fromiso=*    ) fromiso=${param#fromiso=}         ;;
    live         ) live="yes"                        ;;
    ro           ) ro="ro"                           ;;
    rw           ) ro="rw"                           ;;
    quiet        ) export verbose="no"               ;;
    testiso      ) export verbose="yes"              ;;
    testinitrd   ) export verbose="yes"              ;;
  esac
done

if [ -d /lib/modules ] && [ -n "$rootdelay" ] && [ -n "$root" ]; then
        [ "$verbose" == "no" ] || printf "Start udev...\n"
        do_start_udev
fi

if [ -f /etc/mdadm.conf ]; then

  [ "$verbose" == "no" ] || printf "mdadm -As...\n"
  /sbin/mdadm -As

  [ "$verbose" == "no" ] || printf "mdadm --auto-detect...\n"
  /sbin/mdadm --auto-detect
fi  

### First we activate lvm if possible
  if [ -f /sbin/lvm ]; then
    [ "$verbose" == "no" ] || printf "/sbin/lvm vgchange --ignorelockingfailure -ay\n"
    /sbin/lvm vgchange --ignorelockingfailure -ay
    if [ $? = 0 ]; then
       [ "$verbose" == "no" ] || printf "/sbin/lvm vgscan --ignorelockingfailure --mknodes\n"
       /sbin/lvm vgscan --ignorelockingfailure --mknodes
    fi
  fi

if [ -n "$rootdelay" ] ; then
	[ "$verbose" == "no" ] || printf "Wait  %s second(s) ...\n" $rootdelay
	sleep "$rootdelay"
fi

if [ "$live" == "yes" ] || [ "$root" == "" ]; then
	[ "$verbose" == "no" ] || printf "Loading kernel Modules ...\n"
	[ "$verbose" == "no" ] || sleep 2
	LoadModules
	if [ ! -f /sbin/setup-nutyx ]; then
		find_media
		if [ ! -L /dev/yaolinux-cd ]; then
			[ "$verbose" == "no" ] || printf "Media not found yet, trying again in 5 sec\n"
			sleep 5
			find_media
		fi
	fi
	do_resize_rootfs
	do_mount_in_ram

	#
	# If still not find the setup-nutyx file then it's time to giveup
	#
	if [ ! -f /sbin/setup-nutyx ]; then
		no_mount
		sh
	fi
	if [ "$verbose" == "yes" ]; then

		printf "/sbin/setup-nutyx exist ...\n"
		ls -lt /sbin/setup-nutyx
		sleep 5
	fi
fi

if [ "$live" == "yes" ]; then
	# get read of some services
	for i in do_stop_mountfs
	do
		sed -i "/${i}/d" /etc/rc.d/init.d/init_single
	done
	touch /fastboot
	rm /init
	chmod 755 /
	chmod 755 /var
	cd /
	cat > "/usr/share/applications/setup-nutyx.desktop" << "EOF"
[Desktop Entry]
Version=1.0
Name=Install NuTyX on your machine
Comment=Install NuTyX on your machine
GenericName=Setup NuTyX
Exec=sudo /root/bin/setup-nutyx
Terminal=true
Icon=package-x-generic
Categories=System;
Type=Application
StartupNotification=true
EOF
	mkdir -p /root/bin
	cat > /root/bin/setup-nutyx << "EOF"
#!/bin/sh
#
rm -f /etc/sysconfig/console
/sbin/setup-nutyx
EOF
	chmod 755 /root/bin/setup-nutyx
	[ "$verbose" == "no" ] || printf "exec \"%s\" \"%s\" > /dev/null 2>&1 ...\n" "$init" "$@"
	[ "$verbose" == "no" ] || sleep 5
	exec "$init" "$@" > /dev/null 2>&1
fi

if [ "$root" == "" ]; then
	[ "$verbose" == "no" ] || printf "Start udev ...\n"
        do_start_udev

	[ "$verbose" == "no" ] || printf "Start sysklogd ...\n"
	do_start_sysklogd
	[ "$verbose" == "no" ]  && clear

	MainLoop
	root=`cat /root/boot`

	[ "$verbose" == "no" ] || printf "Stop udev ...\n"
	do_stop_udev

	[ "$verbose" == "no" ] || printf "Stop sysklogd ...\n"
	do_stop_sysklogd

	cd /

	for DIR in usr lib
	do
		[ "$verbose" == "no" ] || printf "umount /%s ...\n" $DIR
		umount /$DIR > /dev/null 2>&1
	done
fi

[ -n "$root" ] && LoadModules

mkdir /.root
do_mount_root

if [ -d /lib/modules ] && [ -n "$rootdelay" ]; then
	[ "$verbose" == "no" ] || printf "Stop udev ...\n"
	do_stop_udev
fi

cd /.root
exec switch_root /.root "$init" "$@" > /dev/null 2>&1
